home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Text⁄Files / FaceLift / FaceLift Folder / FLMaca.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-16  |  10.7 KB  |  476 lines  |  [TEXT/KAHL]

  1. /*
  2.  * FLMaca.c - FaceLift routines for reading MACA (MacWrite) files.
  3.  */
  4.  
  5. # include    "FLFileStuff.h"
  6. # include    "FLMaca.h"
  7. # include    "FaceLift.h"
  8.  
  9.  
  10. /* ------------------------------------------------------------ */
  11. /*                        Global variables                        */
  12. /* ------------------------------------------------------------ */
  13.  
  14.  
  15. /*
  16.  * File variables
  17.  */
  18.  
  19.  
  20. Int16        macaFRef;        /* file descriptor */
  21. Str255        macaName;        /* file name */
  22. Int16        macaRefNum;        /* volume reference number */
  23. Int32        paraFilePos;    /* position of last paragraph read */
  24.  
  25.  
  26. /*
  27.  * Document globals
  28.  */
  29.  
  30.  
  31. Int16        version;    /* version number */
  32. Int16        paraOffset;    /* offset to paragraph information */
  33. Int16        mainParas;    /* main doc paragraph count */
  34. Int16        headParas;    /* header paragraph count */
  35. Int16        footParas;    /* footer paragraph count */
  36.  
  37.  
  38. /*
  39.  * Window variables - these are synchronized to only one window
  40.  * at a time
  41.  */
  42.  
  43. Int32        infoPos;    /* position of information array */
  44. Int16        infoLen;    /* length of information array */
  45. Int16        activeFont;    /* font active when saved */
  46. ActiveFace    activeFace;    /* face active when saved */
  47.  
  48.  
  49. /*
  50.  * Pointers to the window variable structures for each window
  51.  */
  52.  
  53. Windows3    *headWind3, *footWind3, *mainWind3;
  54. Windows6    *headWind6, *footWind6, *mainWind6;
  55.  
  56.  
  57. /*
  58.  * Structures for holding document information for each
  59.  * supported version of MacWrite
  60.  */
  61.  
  62. DocInfo3    docInfo3;
  63. DocInfo6    docInfo6;
  64.  
  65.  
  66. /*
  67.  * Miscellaneous
  68.  */
  69.  
  70.  
  71. Handle        paraBuf = nil;    /* buffer for contents of paragraph */
  72. Int16        totalParas;        /* total paragraphs in document */
  73. Int16        paraNum;        /* current paragraph number */
  74. Int16        paraDocType;    /* whether main, header or footer para */
  75. Int16        paraType;        /* paragraph type (text, ruler, picture) */
  76. Int16        paraLen;        /* paragraph length */
  77. Int16        textLen;        /* length of text in text paragraphs */
  78. Int16        formats;        /* number of formats in text paragraph */
  79. Int16        fmtOffset;        /* offset w/in text paragraph to formats */
  80. InfoArray6    **paraInfo6 = nil;    /* info array (for version 6 only) */
  81.  
  82.  
  83.  
  84. /* ------------------------------------------------------------ */
  85. /*                            Local variables                        */
  86. /* ------------------------------------------------------------ */
  87.  
  88. static Int16    paraIndex;        /* paragraph index w/in document window */
  89. static Point    dlogWhere = { 70, 100 };    /* SFGetFile position */
  90.  
  91.  
  92.  
  93. /* ------------------------------------------------------------ */
  94. /*    Document structure -> program variable conversion routines    */
  95. /* ------------------------------------------------------------ */
  96.  
  97.  
  98. /*
  99.  * Convert version 3 globals to unstructured variables
  100.  */
  101.  
  102.  
  103.  
  104. void
  105. GUnstruct3 (Globals3 *g)
  106. {
  107.     paraOffset = g->paraOffset;
  108.     mainParas = g->mainParas;
  109.     headParas = g->headParas;
  110.     footParas = g->footParas;
  111. }
  112.  
  113.  
  114. /*
  115.  * Convert version 3 window variables to unstructured variables
  116.  * *for one document window only*.
  117.  */
  118.  
  119. void
  120. WUnstruct3 (Windows3 *w)
  121. {
  122.     activeFont = w->activeFont;
  123.     activeFace = w->activeFace;
  124. }
  125.  
  126.  
  127. /*
  128.  * Convert version 6 globals to unstructured variables
  129.  */
  130.  
  131. void
  132. GUnstruct6 (Globals6 *g)
  133. {
  134.     mainParas = g->mainParas;
  135.     headParas = g->headParas;
  136.     footParas = g->footParas;
  137. }
  138.  
  139.  
  140. /*
  141.  * Convert version 6 window variables to unstructured variables
  142.  * *for one document window only*.
  143.  */
  144.  
  145. void
  146. WUnstruct6 (Windows6 *w)
  147. {
  148.     infoPos = w->infoPos;
  149.     infoLen = w->infoLen;
  150.     activeFace = w->activeFace;
  151.     activeFont = w->activeFont;
  152. }
  153.  
  154.  
  155.  
  156. /* ------------------------------------------------------------ */
  157. /*                            Input routines                        */
  158. /* ------------------------------------------------------------ */
  159.  
  160.  
  161. /*
  162.  * Open MacWrite file.  Return error code as function result.
  163.  * The mode is fsRdPerm if the file is simply being read, fsRdWrPerm
  164.  * if it's being converted in place.
  165.  *
  166.  * Since every subsequent operation needs to know the version
  167.  * number, that is immediately determined as well.  Also get
  168.  * document information for the current input file, sync the
  169.  * globals and set up the window var pointers.  Initialize variables
  170.  * used for paragraph streaming.  totalParas is set to the total of all
  171.  * the paragraphs in the entire document.  It can be reset to mainParas
  172.  * after the GetDocInfo call if the calling operation only wants to
  173.  * stream the main document paragraphs and skip the header and footer
  174.  * paragraphs.
  175.  */
  176.  
  177. Boolean
  178. OpenMaca (StringPtr fName, int vRefNum)
  179. {
  180. Boolean    result = true;
  181. OSErr    err;
  182.  
  183.     CopyString (fName, macaName);
  184.     macaRefNum = vRefNum;
  185.     if ((err = FSOpen (macaName, macaRefNum, &macaFRef)) != noErr)
  186.     {
  187.         FileErr (err);
  188.         return (false);
  189.     }
  190.  
  191.     /*
  192.      * File opened OK - determine version and do version-specific setup
  193.      */
  194.  
  195.     FileSeek (macaFRef, 0L);            /* version's in the first word */
  196.     (void) FileRead (macaFRef, (Ptr) &version, (Int32) sizeof (Int16));
  197.     FileSeek (macaFRef, 0L);            /* go back to beginning */
  198.  
  199.     switch (version)
  200.     {
  201.  
  202.     case version3:
  203.         (void) FileRead (macaFRef, (Ptr) &docInfo3, (Int32) sizeof (DocInfo3));
  204.         GUnstruct3 (&docInfo3.globals3);
  205.         mainWind3 = &docInfo3.mainWind3;
  206.         headWind3 = &docInfo3.headWind3;
  207.         footWind3 = &docInfo3.footWind3;
  208.         paraBuf = NewHandle (0L);
  209.         totalParas = mainParas + headParas + footParas;
  210.         paraNum = -1;
  211.         break;
  212.  
  213.     case version6:
  214.         (void) FileRead (macaFRef, (Ptr) &docInfo6, (Int32) sizeof (DocInfo6));
  215.         GUnstruct6 (&docInfo6.globals6);
  216.         mainWind6 = &docInfo6.mainWind6;
  217.         headWind6 = &docInfo6.headWind6;
  218.         footWind6 = &docInfo6.footWind6;
  219.         paraBuf = NewHandle (0L);
  220.         paraInfo6 = (InfoArray6 **) NewHandle (0L);
  221.         totalParas = mainParas + headParas + footParas;
  222.         paraNum = -1;
  223.         break;
  224.  
  225.     default:
  226.         Message3 ("\p\"", macaName, "\p\":  Unsupported version of MacWrite");
  227.         CloseMaca ();
  228.         result = false;
  229.         break;
  230.  
  231.     }
  232.  
  233.     return (result);
  234. }
  235.  
  236.  
  237. /*
  238.  * Close MacWrite file and release any associated storage.
  239.  */
  240.  
  241. void
  242. CloseMaca (void)
  243. {
  244.     (void) FSClose (macaFRef);
  245.     (void) FlushVol (nil /*macaFRef*/, macaRefNum);
  246.  
  247.     if (paraBuf != nil)
  248.     {
  249.         DisposeHandle (paraBuf);
  250.         paraBuf = nil;
  251.     }
  252.     if (paraInfo6 != nil)
  253.     {
  254.         DisposeHandle ((Handle) paraInfo6);
  255.         paraInfo6 = nil;
  256.     }
  257. }
  258.  
  259.  
  260. static Boolean
  261. ReadParaBuf (Int16 pLen)
  262. {
  263. Str255    s;
  264. Boolean    result = false;
  265.  
  266.     SetHandleSize (paraBuf, (Int32) pLen);        /* make big enough */
  267.     if (MemError () != noErr)
  268.     {
  269.         NumToString ((long) pLen, s);
  270.         Message3 ("\pCan't read paragraph (memory error).  Trying to read ",
  271.                         s, "\p bytes");
  272.     }
  273.     else
  274.     {
  275.         GetFPos (macaFRef, ¶FilePos);    /* remember paragraph position */
  276.         HLock (paraBuf);
  277.         result = FileRead (macaFRef, *paraBuf, (Int32) pLen);
  278.         HUnlock (paraBuf);
  279.     }
  280.     return (result);
  281. }
  282.  
  283.  
  284. /*
  285.  * Read next version 3 paragraph.
  286.  */
  287.  
  288. static Boolean
  289. ReadPara3 (void)
  290. {
  291.     if (paraNum == 0)        /* set position on first paragraph */
  292.         FileSeek (macaFRef, (Int32) paraOffset);
  293.  
  294.     if (FileRead (macaFRef, (Ptr) ¶Type, (Int32) sizeof (Int16))
  295.         && FileRead (macaFRef,(Ptr)  ¶Len, (Int32) sizeof (Int16))
  296.         && ReadParaBuf (paraLen))
  297.     {
  298.         if (paraType == textPara)
  299.         {
  300.             textLen = * (Int16 *) *paraBuf;    /* number of text bytes */
  301.             fmtOffset = ((textLen + 1) & ~1) + 2;
  302.             formats = * (Int16 *) (*paraBuf + fmtOffset) / sizeof (Format);
  303.             fmtOffset += 2;
  304.         }
  305.         return (true);
  306.     }
  307.     return (false);
  308. }
  309.  
  310.  
  311. /*
  312.  * Sync to window variables and read in paragraph info array
  313.  * for document corresponding to window (main, header, footer).
  314.  */
  315.  
  316. static Boolean
  317. GetInfoArray (Windows6 *w)
  318. {
  319. Str255    s;
  320. Boolean    result = false;
  321.  
  322.     WUnstruct6 (w);                                /* sync window vars */
  323.     SetHandleSize ((Handle) paraInfo6, (Int32) infoLen);    /* make big enough */
  324.     if (MemError () != noErr)
  325.     {
  326.         NumToString ((long) infoLen, s);
  327.         Message3 ("\pCan't read paragraph info (memory error).  Trying to read ",
  328.                         s, "\p bytes");
  329.     }
  330.     else
  331.     {
  332.         FileSeek (macaFRef, (Int32) infoPos);    /* seek to information array */
  333.         HLock ((Handle) paraInfo6);
  334.         result = FileRead (macaFRef, (Ptr) *paraInfo6, (Int32) infoLen);    /* read it */
  335.         HUnlock ((Handle) paraInfo6);
  336.         paraIndex = -1;
  337.     }
  338.     return (result);
  339. }
  340.  
  341.  
  342. /*
  343.  * Read next version 6 paragraph.
  344.  *
  345.  * If this is the first paragraph of the main, header or footer
  346.  * document, sync to the window variables for the correct document
  347.  * and read in the paragraph info array.
  348.  *
  349.  * If the paragraph contains compressed text, textLen is the number
  350.  * of *uncompressed* chars in the paragraph, so have to figure out
  351.  * how many bytes the text actually take up in order to find the
  352.  * format information.
  353.  */
  354.  
  355. static Boolean
  356. ReadPara6 (void)
  357. {
  358. ParaInfo6    info;
  359. Boolean                result = true;
  360. int        count;
  361. Boolean    firstHalf;
  362. Byte        *p;
  363. int        nibble;
  364.  
  365.     if (paraNum == 0)                            /* first paragraph of main? */
  366.         result = GetInfoArray (mainWind6);
  367.     else if (paraNum == mainParas)                /* first paragraph of head? */
  368.         result = GetInfoArray (headWind6);
  369.     else if (paraNum == mainParas + headParas)    /* first paragraph of foot? */
  370.         result = GetInfoArray (footWind6);
  371.     
  372.     if (result == false)
  373.         return (false);        /* couldn't read info array - trouble! */
  374.  
  375.     info = (**paraInfo6)[++paraIndex];
  376.     paraType = info.paraHeight;
  377.     if (paraType < 0)
  378.         paraType = pictPara;
  379.     else if (paraType == 0)
  380.         paraType = rulerPara;
  381.     else
  382.         paraType = textPara;
  383.  
  384.     paraLen = info.paraLen;
  385.  
  386.     FileSeek (macaFRef, info.paraStOff.paraOffset & 0x00ffffff);
  387.  
  388.     if (ReadParaBuf (paraLen) == false)
  389.         return (false);
  390.  
  391.     if (paraType == textPara)
  392.     {
  393.         textLen = * (Int16 *) *paraBuf;    /* number of text bytes */
  394.         if ((info.paraStOff.paraStatus & stCompress) == 0)
  395.         {
  396.             fmtOffset = ((textLen + 1) & ~1) + 2;    /* uncompressed */
  397.         }
  398.         else
  399.         {
  400.             HLock (paraBuf);
  401.             p = (Byte *) (*paraBuf + 2);
  402.             count = 0;
  403.             firstHalf = true;
  404.             while (count < textLen)
  405.             {
  406.                 if (firstHalf)
  407.                     nibble = ((Byte) *p) >> 4;
  408.                 else
  409.                     nibble = *p++ & 0x0f;
  410.                 if (nibble == 15)
  411.                     ++p;
  412.                 firstHalf = !firstHalf;
  413.                 ++count;
  414.             }
  415.             if (!firstHalf)            /* want p to end up on first byte */
  416.                 ++p;                /* past end of compressed text */
  417.  
  418.             fmtOffset = ((char *) p - *paraBuf + 1) & ~1;
  419.             HUnlock (paraBuf);
  420.         }
  421.  
  422.         formats = * (Int16 *) (*paraBuf + fmtOffset) / sizeof (Format);
  423.         fmtOffset += 2;
  424.     }
  425.  
  426.     return (true);
  427. }
  428.  
  429.  
  430. /*
  431.  * Read a paragraph.  Returns false if it couldn't be read, or if at
  432.  * end of file.  Sets paraDocType to the document type (main, header,
  433.  * footer).
  434.  *
  435.  * The paragraphs are read in the order:  main, header, footer.  This
  436.  * order is dictated by the file structure for version 3 and for
  437.  * consistency is mimicked for version 6 files (see ReadPara6).
  438.  *
  439.  * If the paragraph is a text paragraph, get the text length (in first
  440.  * two bytes), and the format offset (in the two bytes on the word
  441.  * boundary following the text.  The format offset is left pointing to
  442.  * the actual format data, not the format length word immediately
  443.  * preceding.
  444.  */
  445.  
  446. Boolean
  447. ReadPara (void)
  448. {
  449. Boolean    result;
  450.  
  451.     if (++paraNum >= totalParas)
  452.         return (false);
  453.     
  454.     if (paraNum < mainParas)
  455.         paraDocType = mainDoc;
  456.     else if (paraNum < mainParas + headParas)
  457.         paraDocType = headDoc;
  458.     else
  459.         paraDocType = footDoc;
  460.  
  461.     switch (version)
  462.     {
  463.  
  464.     case version3:
  465.         result = ReadPara3 ();
  466.         break;
  467.  
  468.     case version6:
  469.         result = ReadPara6 ();
  470.         break;
  471.  
  472.     }
  473.  
  474.     return (result);
  475. }
  476.